Skip to content

Conversation

XChy
Copy link
Member

@XChy XChy commented Oct 10, 2025

Resolves #162240 (review)

@llvmbot
Copy link
Member

llvmbot commented Oct 10, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Hongyu Chen (XChy)

Changes

Resolves #162240 (review)


Full diff: https://github.com/llvm/llvm-project/pull/162802.diff

1 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp (+26-27)
diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
index f4e05a204c9cf..65e6cc9aa1a7b 100644
--- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
@@ -148,19 +148,17 @@ class SelectInstToUnfold {
 
 class DFAJumpThreading {
 public:
-  DFAJumpThreading(AssumptionCache *AC, DominatorTree *DT, LoopInfo *LI,
+  DFAJumpThreading(AssumptionCache *AC, DomTreeUpdater *DTU, LoopInfo *LI,
                    TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE)
-      : AC(AC), DT(DT), LI(LI), TTI(TTI), ORE(ORE) {}
+      : AC(AC), DTU(DTU), LI(LI), TTI(TTI), ORE(ORE) {}
 
   bool run(Function &F);
   bool LoopInfoBroken;
 
 private:
   void
-  unfoldSelectInstrs(DominatorTree *DT,
-                     const SmallVector<SelectInstToUnfold, 4> &SelectInsts) {
+  unfoldSelectInstrs(const SmallVector<SelectInstToUnfold, 4> &SelectInsts) {
     // TODO: Have everything use a single lazy DTU
-    DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
     SmallVector<SelectInstToUnfold, 4> Stack(SelectInsts);
 
     while (!Stack.empty()) {
@@ -168,7 +166,7 @@ class DFAJumpThreading {
 
       std::vector<SelectInstToUnfold> NewSIsToUnfold;
       std::vector<BasicBlock *> NewBBs;
-      unfold(&DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
+      unfold(DTU, LI, SIToUnfold, &NewSIsToUnfold, &NewBBs);
 
       // Put newly discovered select instructions into the work list.
       llvm::append_range(Stack, NewSIsToUnfold);
@@ -181,7 +179,7 @@ class DFAJumpThreading {
                      std::vector<BasicBlock *> *NewBBs);
 
   AssumptionCache *AC;
-  DominatorTree *DT;
+  DomTreeUpdater *DTU;
   LoopInfo *LI;
   TargetTransformInfo *TTI;
   OptimizationRemarkEmitter *ORE;
@@ -869,11 +867,11 @@ struct AllSwitchPaths {
 };
 
 struct TransformDFA {
-  TransformDFA(AllSwitchPaths *SwitchPaths, DominatorTree *DT,
+  TransformDFA(AllSwitchPaths *SwitchPaths, DomTreeUpdater *DTU,
                AssumptionCache *AC, TargetTransformInfo *TTI,
                OptimizationRemarkEmitter *ORE,
                SmallPtrSet<const Value *, 32> EphValues)
-      : SwitchPaths(SwitchPaths), DT(DT), AC(AC), TTI(TTI), ORE(ORE),
+      : SwitchPaths(SwitchPaths), DTU(DTU), AC(AC), TTI(TTI), ORE(ORE),
         EphValues(EphValues) {}
 
   bool run() {
@@ -1049,19 +1047,16 @@ struct TransformDFA {
     SmallPtrSet<BasicBlock *, 16> BlocksToClean;
     BlocksToClean.insert_range(successors(SwitchBlock));
 
-    {
-      DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Lazy);
-      for (const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
-        createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, &DTU);
-        NumPaths++;
-      }
-
-      // After all paths are cloned, now update the last successor of the cloned
-      // path so it skips over the switch statement
-      for (const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
-        updateLastSuccessor(TPath, DuplicateMap, &DTU);
+    for (const ThreadingPath &TPath : SwitchPaths->getThreadingPaths()) {
+      createExitPath(NewDefs, TPath, DuplicateMap, BlocksToClean, DTU);
+      NumPaths++;
     }
 
+    // After all paths are cloned, now update the last successor of the cloned
+    // path so it skips over the switch statement
+    for (const ThreadingPath &TPath : SwitchPaths->getThreadingPaths())
+      updateLastSuccessor(TPath, DuplicateMap, DTU);
+
     // For each instruction that was cloned and used outside, update its uses
     updateSSA(NewDefs);
 
@@ -1165,7 +1160,7 @@ struct TransformDFA {
     }
     // SSAUpdater handles phi placement and renaming uses with the appropriate
     // value.
-    SSAUpdate.RewriteAllUses(DT);
+    SSAUpdate.RewriteAllUses(&DTU->getDomTree());
   }
 
   /// Clones a basic block, and adds it to the CFG.
@@ -1388,7 +1383,7 @@ struct TransformDFA {
   }
 
   AllSwitchPaths *SwitchPaths;
-  DominatorTree *DT;
+  DomTreeUpdater *DTU;
   AssumptionCache *AC;
   TargetTransformInfo *TTI;
   OptimizationRemarkEmitter *ORE;
@@ -1431,7 +1426,7 @@ bool DFAJumpThreading::run(Function &F) {
                       << "candidate for jump threading\n");
     LLVM_DEBUG(SI->dump());
 
-    unfoldSelectInstrs(DT, Switch.getSelectInsts());
+    unfoldSelectInstrs(Switch.getSelectInsts());
     if (!Switch.getSelectInsts().empty())
       MadeChanges = true;
 
@@ -1453,7 +1448,7 @@ bool DFAJumpThreading::run(Function &F) {
   }
 
 #ifdef NDEBUG
-  LI->verify(*DT);
+  LI->verify(DTU->getDomTree());
 #endif
 
   SmallPtrSet<const Value *, 32> EphValues;
@@ -1461,13 +1456,15 @@ bool DFAJumpThreading::run(Function &F) {
     CodeMetrics::collectEphemeralValues(&F, AC, EphValues);
 
   for (AllSwitchPaths SwitchPaths : ThreadableLoops) {
-    TransformDFA Transform(&SwitchPaths, DT, AC, TTI, ORE, EphValues);
+    TransformDFA Transform(&SwitchPaths, DTU, AC, TTI, ORE, EphValues);
     if (Transform.run())
       MadeChanges = LoopInfoBroken = true;
   }
 
+  DTU->flush();
+
 #ifdef EXPENSIVE_CHECKS
-  assert(DT->verify(DominatorTree::VerificationLevel::Full));
+  assert(DTU->getDomTree().verify(DominatorTree::VerificationLevel::Full));
   verifyFunction(F, &dbgs());
 #endif
 
@@ -1482,7 +1479,9 @@ PreservedAnalyses DFAJumpThreadingPass::run(Function &F,
   LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
   TargetTransformInfo &TTI = AM.getResult<TargetIRAnalysis>(F);
   OptimizationRemarkEmitter ORE(&F);
-  DFAJumpThreading ThreadImpl(&AC, &DT, &LI, &TTI, &ORE);
+
+  DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
+  DFAJumpThreading ThreadImpl(&AC, &DTU, &LI, &TTI, &ORE);
   if (!ThreadImpl.run(F))
     return PreservedAnalyses::all();
 

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@XChy XChy enabled auto-merge (squash) October 10, 2025 08:39
@XChy XChy merged commit 881a57b into llvm:main Oct 10, 2025
9 of 10 checks passed
@mikaelholmen
Copy link
Collaborator

Hi @XChy

The following starts failing with this patch:
opt -passes="dfa-jump-threading,loop(loop-flatten)" bbi-111476.ll -o /dev/null
It crashes with:

opt: ../lib/Transforms/Utils/LCSSA.cpp:422: bool formLCSSAImpl(Loop &, const DominatorTree &, const LoopInfo *, ScalarEvolution *, LoopExitBlocksTy &): Assertion `L.isLCSSAForm(DT)' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: build-all/bin/opt -passes=dfa-jump-threading,loop(loop-flatten) bbi-111476.ll -o /dev/null
1.	Running pass "function(dfa-jump-threading,loop(loop-flatten))" on module "bbi-111476.ll"
2.	Running pass "loop(loop-flatten)" on function "func_23"
3.	Running pass "lcssa" on function "func_23"
 #0 0x000055aec3cb4c46 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all/bin/opt+0x4ceac46)
 #1 0x000055aec3cb21d5 llvm::sys::RunSignalHandlers() (build-all/bin/opt+0x4ce81d5)
 #2 0x000055aec3cb5dc9 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007f7a99a77990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007f7a9741752f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007f7a973eae65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x00007f7a973ead39 _nl_load_domain.cold.0 (/lib64/libc.so.6+0x21d39)
 #7 0x00007f7a9740fe86 (/lib64/libc.so.6+0x46e86)
 #8 0x000055aec4620461 (build-all/bin/opt+0x5656461)
 #9 0x000055aec462057c formLCSSARecursivelyImpl(llvm::Loop&, llvm::DominatorTree const&, llvm::LoopInfo const*, llvm::ScalarEvolution*, llvm::SmallDenseMap<llvm::Loop*, llvm::SmallVector<llvm::BasicBlock*, 1u>, 4u, llvm::DenseMapInfo<llvm::Loop*, void>, llvm::detail::DenseMapPair<llvm::Loop*, llvm::SmallVector<llvm::BasicBlock*, 1u>>>&) LCSSA.cpp:0:0
#10 0x000055aec4620862 llvm::LCSSAPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x5656862)
#11 0x000055aec519c58d llvm::detail::PassModel<llvm::Function, llvm::LCSSAPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#12 0x000055aec3ed78f5 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x4f0d8f5)
#13 0x000055aec544c070 llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x6482070)
#14 0x000055aec519ef6d llvm::detail::PassModel<llvm::Function, llvm::FunctionToLoopPassAdaptor, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#15 0x000055aec3ed78f5 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x4f0d8f5)
#16 0x000055aec51a0c4d llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#17 0x000055aec3edc1fe llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x4f121fe)
#18 0x000055aec512fa8d llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) NewPMDriver.cpp:0:0
#19 0x000055aec3ed65c5 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x4f0c5c5)
#20 0x000055aec5128750 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (build-all/bin/opt+0x615e750)
#21 0x000055aec3c55eda optMain (build-all/bin/opt+0x4c8beda)
#22 0x00007f7a974037e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#23 0x000055aec3c5392e _start (build-all/bin/opt+0x4c8992e)
Abort (core dumped)

https://llvm.godbolt.org/z/exTxoo431

bbi-111476.ll.gz

@mikaelholmen
Copy link
Collaborator

Another crash like this:
opt -verify-loop-info -passes="dfa-jump-threading,loop-mssa(loop-idiom-vectorize)" bbi-111484.ll -o /dev/null

Result:

opt: ../include/llvm/Support/GenericLoopInfoImpl.h:733: void llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>::verify(const DomTreeBase<BlockT> &) const [N = llvm::BasicBlock, M = llvm::Loop]: Assertion `L->contains(BB) && "orphaned block"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0.	Program arguments: build-all/bin/opt -verify-loop-info -passes=dfa-jump-threading,loop-mssa(loop-idiom-vectorize) bbi-111484.ll -o /dev/null
1.	Running pass "function(dfa-jump-threading,loop-mssa(loop-idiom-vectorize))" on module "bbi-111484.ll"
2.	Running pass "loop-mssa(loop-idiom-vectorize)" on function "f316"
 #0 0x000055dd01bdac46 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (build-all/bin/opt+0x4ceac46)
 #1 0x000055dd01bd81d5 llvm::sys::RunSignalHandlers() (build-all/bin/opt+0x4ce81d5)
 #2 0x000055dd01bdbdc9 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x00007feb181c2990 __restore_rt (/lib64/libpthread.so.0+0x12990)
 #4 0x00007feb15b6252f raise (/lib64/libc.so.6+0x4e52f)
 #5 0x00007feb15b35e65 abort (/lib64/libc.so.6+0x21e65)
 #6 0x00007feb15b35d39 _nl_load_domain.cold.0 (/lib64/libc.so.6+0x21d39)
 #7 0x00007feb15b5ae86 (/lib64/libc.so.6+0x46e86)
 #8 0x000055dd022f2994 llvm::LoopInfoBase<llvm::BasicBlock, llvm::Loop>::verify(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) const (build-all/bin/opt+0x5402994)
 #9 0x000055dd03372abe llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x6482abe)
#10 0x000055dd030c4f6d llvm::detail::PassModel<llvm::Function, llvm::FunctionToLoopPassAdaptor, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#11 0x000055dd01dfd8f5 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (build-all/bin/opt+0x4f0d8f5)
#12 0x000055dd030c6c4d llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) PassBuilderPipelines.cpp:0:0
#13 0x000055dd01e021fe llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x4f121fe)
#14 0x000055dd03055a8d llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) NewPMDriver.cpp:0:0
#15 0x000055dd01dfc5c5 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (build-all/bin/opt+0x4f0c5c5)
#16 0x000055dd0304e750 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (build-all/bin/opt+0x615e750)
#17 0x000055dd01b7beda optMain (build-all/bin/opt+0x4c8beda)
#18 0x00007feb15b4e7e5 __libc_start_main (/lib64/libc.so.6+0x3a7e5)
#19 0x000055dd01b7992e _start (build-all/bin/opt+0x4c8992e)
Abort (core dumped)

bbi-111484.ll.gz

@XChy
Copy link
Member Author

XChy commented Oct 13, 2025

This patch seems not to be blamed. It looks like we insert an additional edge to domtree during unfolding selects, though I am on a vacation recently and have no chance to debug it now.

@mikaelholmen
Copy link
Collaborator

This patch seems not to be blamed..

Well, both reproducers I attached at least starts crashing with this patch.

@XChy
Copy link
Member Author

XChy commented Oct 13, 2025

This patch seems not to be blamed..

Well, both reproducers I attached at least starts crashing with this patch.

That's OK for bisection, as this patch exposes the problems. Thanks for the reports anyway. I will fix them once I have a chance.

DharuniRAcharya pushed a commit to DharuniRAcharya/llvm-project that referenced this pull request Oct 13, 2025
UsmanNadeem added a commit that referenced this pull request Oct 14, 2025
…ing (#163296)

The edge `StartBlock -> EndBlock` already exists before unfolding.

The instructions for `applyUpdates()` say that you are supposed not
to insert an existing edge.

Fixes issues reported by @mikaelholmen in
#162802
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Oct 14, 2025
…hile unfolding (#163296)

The edge `StartBlock -> EndBlock` already exists before unfolding.

The instructions for `applyUpdates()` say that you are supposed not
to insert an existing edge.

Fixes issues reported by @mikaelholmen in
llvm/llvm-project#162802
akadutta pushed a commit to akadutta/llvm-project that referenced this pull request Oct 14, 2025
akadutta pushed a commit to akadutta/llvm-project that referenced this pull request Oct 14, 2025
…ing (llvm#163296)

The edge `StartBlock -> EndBlock` already exists before unfolding.

The instructions for `applyUpdates()` say that you are supposed not
to insert an existing edge.

Fixes issues reported by @mikaelholmen in
llvm#162802
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants